/******************************************************************************
* Copyright (C) 2018, Huada Semiconductor Co.,Ltd All rights reserved.
*
* This software is owned and published by:
* Huada Semiconductor Co.,Ltd ("HDSC").
*
* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
*
* This software contains source code for use with HDSC
* components. This software is licensed by HDSC to be adapted only
* for use in systems utilizing HDSC components. HDSC shall not be
* responsible for misuse or illegal use of this software for devices not
* supported herein. HDSC is providing this software "AS IS" and will
* not be responsible for issues arising from incorrect user implementation
* of the software.
*
* Disclaimer:
* HDSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
* REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS),
* ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
* WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
* WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
* WARRANTY OF NONINFRINGEMENT.
* HDSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
* NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
* LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
* LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
* INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
* SAVINGS OR PROFITS,
* EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
* INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
* FROM, THE SOFTWARE.
*
* This software may be replicated in part or whole for the licensed use,
* with the restriction that this Disclaimer and Copyright notice must be
* included with each copy of this software, whether used in part or whole,
* at all times.
*/
/******************************************************************************/
/** \file main.c
 **
 ** A detailed description is available at
 ** @link Sample Group Some description @endlink
 **
 **   - 2019-03-26  1.0  Lux First version for Device Driver Library of Module.
 **
 ******************************************************************************/

/******************************************************************************
 * Include files
 ******************************************************************************/
#include <stdio.h>
#include "bsp_init.h"
#include "hc32_ll.h"
#include "hc32_ll_clk.h"
#include "hc32_ll_utility.h"
#include "hc32_ll_usart.h"

/******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/
/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/
/* UART RX/TX Port/Pin definition */
#define USART_RX_PORT                   (GPIO_PORT_B)   /* PB09: USART3_RX */
#define USART_RX_PIN                    (GPIO_PIN_09)
#define USART_RX_GPIO_FUNC              (GPIO_FUNC_33)

#define USART_TX_PORT                   (GPIO_PORT_B)   /* PB08: USART3_TX */
#define USART_TX_PIN                    (GPIO_PIN_08)
#define USART_TX_GPIO_FUNC              (GPIO_FUNC_32)

/* USART unit definition */
#define USART_UNIT                      (CM_USART3)
#define USART_FCG_ENABLE()              (FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_USART3, ENABLE))

/* USART interrupt definition */
#define USART_RX_ERR_IRQn               (INT000_IRQn)
#define USART_RX_ERR_INT_SRC            (INT_SRC_USART3_EI)

#define USART_RX_FULL_IRQn              (INT001_IRQn)
#define USART_RX_FULL_INT_SRC           (INT_SRC_USART3_RI)
/******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/
/**
 * @brief  BSP clock initialize.
 *         SET board system clock to PLLH@240MHz
 *         Flash: 5 wait
 *         SRAM_HS: 1 wait
 *         SRAM1_2_3_4_B: 2 wait
 *         PCLK0: 240MHz
 *         PCLK1: 120MHz
 *         PCLK2: 60MHz
 *         PCLK3: 60MHz
 *         PCLK4: 120MHz
 *         EXCLK: 120MHz
 *         HCLK:  240MHz
 * @param  None
 * @retval None
 */
void BSP_CLK_Init(void)
{
  stc_clock_xtal_init_t stcXtalInit;
  stc_clock_pll_init_t stcPLLHInit;

  /* PCLK0, HCLK  Max 240MHz */
  /* PCLK1, PCLK4 Max 120MHz */
  /* PCLK2, PCLK3 Max 60MHz  */
  /* EX BUS Max 120MHz */
  CLK_SetClockDiv(CLK_BUS_CLK_ALL, \
                  (CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | \
                   CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 | \
                   CLK_HCLK_DIV1));

  (void)CLK_XtalStructInit(&stcXtalInit);
  /* Config Xtal and enable Xtal */
  stcXtalInit.u8Mode       = CLK_XTAL_MD_OSC;
  stcXtalInit.u8Drv        = CLK_XTAL_DRV_ULOW;
  stcXtalInit.u8State      = CLK_XTAL_ON;
  stcXtalInit.u8StableTime = CLK_XTAL_STB_2MS;
  (void)CLK_XtalInit(&stcXtalInit);

  (void)CLK_PLLStructInit(&stcPLLHInit);
  /* VCO = (8/1)*50 = 400MHz*/
  stcPLLHInit.u8PLLState = CLK_PLL_ON;
  stcPLLHInit.PLLCFGR = 0UL;
  stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLN = 50UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLP = 2UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLQ = 2UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLR = 2UL - 1UL;
  stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL;
  (void)CLK_PLLInit(&stcPLLHInit);

  /* Highspeed SRAM set to 0 Read/Write wait cycle */
  SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE0, SRAM_WAIT_CYCLE0);

  /* SRAM1_2_3_4_backup set to 1 Read/Write wait cycle */
  SRAM_SetWaitCycle((SRAM_SRAM12 | SRAM_SRAM3 | SRAM_SRAMR), SRAM_WAIT_CYCLE1, SRAM_WAIT_CYCLE1);

  /* 0-wait @ 40MHz */
  (void)EFM_SetWaitCycle(EFM_WAIT_CYCLE5);

  /* 4 cycles for 200MHz */
  GPIO_SetReadWaitCycle(GPIO_RD_WAIT3);

  CLK_SetSysClockSrc(CLK_SYSCLK_SRC_PLL);
}


/**
 ******************************************************************************
 ** \brief  Main function of project
 **
 ** \return uint32_t return value, if needed
 **
 ** This sample
 **
 ******************************************************************************/
/**
 * @brief  USART RX error IRQ callback.
 * @param  None
 * @retval None
 */
static void USART_RxError_IrqCallback(void)
{
  if (SET == USART_GetStatus(USART_UNIT, (USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR))) {
    (void)USART_ReadData(USART_UNIT);
  }
  USART_ClearStatus(USART_UNIT, (USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR | USART_FLAG_OVERRUN));
}

/**
 * @brief  USART RX IRQ callback
 * @param  None
 * @retval None
 */
static void USART_RxFull_IrqCallback(void)
{
  uint8_t u8Data = (uint8_t)USART_ReadData(USART_UNIT);
  u8Data = u8Data;
}

/**
 * @brief  Instal IRQ handler.
 * @param  [in] pstcConfig      Pointer to struct @ref stc_irq_signin_config_t
 * @param  [in] u32Priority     Interrupt priority
 * @retval None
 */
static void INTC_IrqInstalHandler(const stc_irq_signin_config_t *pstcConfig, uint32_t u32Priority)
{
  if (NULL != pstcConfig) {
    (void)INTC_IrqSignIn(pstcConfig);
    NVIC_ClearPendingIRQ(pstcConfig->enIRQn);
    NVIC_SetPriority(pstcConfig->enIRQn, u32Priority);
    NVIC_EnableIRQ(pstcConfig->enIRQn);
  }
}

//串口模块配置
void Uart_Config(CM_USART_TypeDef* USARTx ,uint32_t baud)
{
  stc_usart_uart_init_t stcUartInit;
  stc_irq_signin_config_t stcIrqSigninConfig;
	
  /* Configure USART RX/TX pin. */
  GPIO_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_GPIO_FUNC);
  GPIO_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_GPIO_FUNC);

  /* Enable peripheral clock */
  USART_FCG_ENABLE();

  /* Initialize UART. */
  (void)USART_UART_StructInit(&stcUartInit);
  stcUartInit.u32ClockDiv = USART_CLK_DIV64;
  stcUartInit.u32Baudrate = baud;
  stcUartInit.u32OverSampleBit = USART_OVER_SAMPLE_8BIT;
  if (LL_OK != USART_UART_Init(USART_UNIT, &stcUartInit, NULL)) {
    for (;;) {
    }
  }
  /* Register RX error IRQ handler && configure NVIC. */
  stcIrqSigninConfig.enIRQn = USART_RX_ERR_IRQn;
  stcIrqSigninConfig.enIntSrc = USART_RX_ERR_INT_SRC;
  stcIrqSigninConfig.pfnCallback = &USART_RxError_IrqCallback;
  INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);

  /* Register RX full IRQ handler && configure NVIC. */
  stcIrqSigninConfig.enIRQn = USART_RX_FULL_IRQn;
  stcIrqSigninConfig.enIntSrc = USART_RX_FULL_INT_SRC;
  stcIrqSigninConfig.pfnCallback = &USART_RxFull_IrqCallback;
  INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);

  /* Enable RX/TX function */
  USART_FuncCmd(USART_UNIT, (USART_RX | USART_INT_RX | USART_TX), ENABLE);
}


int Debug_Uart_Init(void)
{
  Uart_Config(USART_UNIT,115200);
  return 0;
}
//INIT_BOARD_EXPORT(Debug_Uart_Init);


int32_t Debug_Uart_SendDataPoll(uint8_t u8Data)
{
  uint16_t timeout;
  int32_t i32Ret = LL_OK;
  timeout = 0;

  while(++timeout<60000)
  {
    if(USART_GetStatus(USART_UNIT, USART_FLAG_TX_EMPTY)) break;
  }
  USART_WriteData(USART_UNIT, u8Data);
  timeout = 0;
  while(++timeout<60000)
  {
    if(USART_GetStatus(USART_UNIT, USART_FLAG_TX_CPLT)) break;
  }
  return i32Ret;
}



#if (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) || \
    (defined (__ICCARM__) && (__VER__ < 9000000)) || (defined (__CC_ARM))
/**
 * @brief  Re-target fputc function.
 * @param  [in] ch
 * @param  [in] f
 * @retval int32_t
 */
int32_t fputc(int32_t ch, FILE *f)
{
    (void)f;  /* Prevent unused argument compilation warning */

    return (LL_OK == Debug_Uart_SendDataPoll((char)ch)) ? ch : -1;
}

#elif (defined (__ICCARM__) && (__VER__ >= 9000000))

#include <LowLevelIOInterface.h>
#pragma module_name = "?__write"
size_t __dwrite(int handle, const unsigned char *buffer, size_t size)
{
    size_t nChars = 0;
    size_t i;

    if (buffer == NULL) {
        /*
         * This means that we should flush internal buffers.  Since we
         * don't we just return.  (Remember, "handle" == -1 means that all
         * handles should be flushed.)
         */
        return 0;
    }

    /* This template only writes to "standard out" and "standard err",
     * for all other file handles it returns failure. */
    if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) {
        return _LLIO_ERROR;
    }

    for (i = 0; i < size; i++) {
        if (Debug_Uart_SendDataPoll((char)buffer[i]) < 0) {
            return _LLIO_ERROR;
        }

        ++nChars;
    }

    return nChars;
}

#elif defined (__GNUC__) && !defined (__CC_ARM)

#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>

__attribute__((weak)) int _isatty(int fd)
{
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
    return 1;
  errno = EBADF;
    return 0;
}

__attribute__((weak)) int _close(int fd)
{
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
    return 0;
  errno = EBADF;
    return -1;
}

__attribute__((weak)) int _lseek(int fd, int ptr, int dir)
{
  (void)fd;
  (void)ptr;
  (void)dir;

  errno = EBADF;
  return -1;
}

__attribute__((weak)) int _fstat(int fd, struct stat *st)
{
  if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
  {
    st->st_mode = S_IFCHR;
    return 0;
  }
  errno = EBADF;
  return 0;
}

__attribute__((weak)) int _read(int file, char *ptr, int len)
{
  (void)file;
  int DataIdx;
  for (DataIdx = 0; DataIdx < len; DataIdx++)
  {
    ptr++ ;
  }
  return len;
}

__attribute__((weak)) void _getpid(void)
{
  ;
}

__attribute__((weak)) void _kill(void)
{
  ;
}
/**
 * @brief  Re-target _write function.
 * @param  [in] fd
 * @param  [in] data
 * @param  [in] size
 * @retval int32_t
 */
int32_t _write(int fd, char data[], int32_t size)
{
    int32_t i = -1;

    if (NULL != data) {
        (void)fd;  /* Prevent unused argument compilation warning */

        for (i = 0; i < size; i++) {
            if (LL_OK != Debug_Uart_SendDataPoll(data[i])) {
                break;
            }
        }
    }

    return i ? i : -1;
}

#endif
/******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
